from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse
from utilss.redis_pool import POOL
from rest_framework.response import Response
from rest_framework.serializers import Serializer
from hashlib import md5
from Crypto.Cipher import AES
import json
import redis
import time


class EncryptionAndDecryption(MiddlewareMixin):
    def process_request(self, request):
        pass

    def process_response(self, request, response):
        """
        此处对返回的数据进行加密，保障安全性
        功能尚未完善！
        :param request:
        :param response:
        :return:
        """
        url = request.get_full_path()
        url_list = [
            '/db_access/server/',
            '/db_access/dick/',
            '/db_access/memory/',
            '/db_access/nic/',
            '/db_access/assets_change/',
            '/db_access/error_log/',
        ]
        if url in url_list:
            pass
        return response

    def process_view(self, request, view_name, *args, **kwargs):
        """
        对访问 /api/agent/ 路径的 client进行校验，是否为安全用户！
        :param request:
        :param view_name:
        :param args:
        :param kwargs:
        :return:
        """
        agent = request.get_full_path()
        if agent == '/api/agent/':
            auth_key = request.META['HTTP_AUTHENTICATION']
            old_time = float(auth_key.split('|')[-1])
            now_key = self.get_key(old_time)
            new_time = time.time()

            if new_time - old_time <= 5 and now_key == auth_key:
                client = redis.Redis(connection_pool=POOL)
                if not client.get(auth_key):
                    client.set(auth_key, auth_key)
                    client.expire(auth_key, 50)
                else:
                    return HttpResponse('验证失败！')
            else:
                return HttpResponse('验证失败！')

    def process_template_response(self, request, response):
        return response

    def process_exception(self, request, exception):
        pass

    def get_key(self, old_time):
        key_one = md5()
        auth_key = 'zhangzhuowei|2021/8/29 15:30|version1'
        key_one.update(auth_key.encode('utf8'))
        encrypted_string_one = key_one.hexdigest() + '|' + str(old_time)
        key_twe = md5(encrypted_string_one.encode('utf8'))
        encrypted_string_twe = key_twe.hexdigest() + '|' + str(old_time)
        return encrypted_string_twe

    def encrypt(self, message):
        """
        :param message: 传入需要加密的数据，字符串类型
        :return: 返回被加密后的字节，bytes类型，无法使用utf-8/gbk解码
        """
        key = b'abcdefghijklmnop'  # 私钥，bytes类型，要求字符个数为16的倍数
        cipher = AES.new(key, AES.MODE_CBC, key)  # 生成AES，每次加密/解密都需重新生成
        bmessage = bytearray(message, encoding='utf-8')  # 将字符串转换为bytesarrary类型
        length = len(bytes(message, encoding='utf-8'))  # 获取bytes列表的长度
        remainder = length % 16  # 该长度 % 16, 获取商和余数
        difference_value = 16 - remainder  # 获取bytes列表距离为16的整数倍的差值
        for i in range(difference_value):  # 循环补全所剩的差值，直到为16的倍数
            bmessage.append(32)  # 此处32代表空格的ascii码
        msg = cipher.encrypt(bmessage)  # 将message加密, 需要的参数为bytes类型
        return msg  # 返回加密后的数据，是bytes类型

    def decrypt(self, aes_bytes):
        """
        :param aes_bytes: 被AES加密后返回的字节数据，bytes类型
        :return: 返回解密后的数据，字符串类型
        """
        key = b'abcdefghijklmnop'  # 私钥，bytes类型，要求字符个数为16的倍数
        cipher = AES.new(key, AES.MODE_CBC, key)  # 生成AES，每次加密/解密都需重新生成
        result = cipher.decrypt(aes_bytes)  # 将字符串进行解密，参数需要为bytes类型
        return result.decode('utf-8').strip()  # 返回解密后的数据，字符串类型

